package cn.gwm.flink.streaming.strategy.vehiclepredict;

import cn.gwm.flink.streaming.constant.ChargePredictFields;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;

import java.math.BigDecimal;
import java.util.*;

/**
 * @author : GW00280745
 * @date : 2022/7/23 15:11
 * @description : map表的坐标值 和mysql绑定，进行动态更新
 */
public class AxisInfo {
    private volatile static AxisInfo instance;
    public static AxisInfo singleInstance() {
        if (instance == null) {
            synchronized (AxisInfo.class) {
                if (instance == null) {
                    instance = new AxisInfo();
                }
            }
        }
        return instance;
    }
    public JSONObject batterSocAvg(BigDecimal factor,Long tid,JSONObject jsonObject){
        jsonObject.put(tid.toString(),factor);
        ArrayList<String> list = new ArrayList<>();
        for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
            String key = entry.getKey();
            if (StringUtils.equalsIgnoreCase(key,"avg")){
                continue;
            }
            Object value = entry.getValue();
            String concat = key.concat(ChargePredictFields.ins().char3).concat(value.toString());
            list.add(concat);
        }
        Collections.sort(list, new Comparator<Object>() {
            @Override
            public int compare(Object o1, Object o2) {
                String s1 = StringUtils.substringBefore(o1.toString(), ChargePredictFields.ins().char3);
                String s2 = StringUtils.substringBefore(o2.toString(), ChargePredictFields.ins().char3);
                return s1.compareTo(s2);
            }
        });
        if (list.size()>DwsStrConstant.ins().num5){
            String s = list.get(0);
            String s1 = StringUtils.substringBefore(s, ChargePredictFields.ins().char3);
            jsonObject.remove(s1);
            list.remove(0);
        }
        BigDecimal sum = new BigDecimal(0);
        for (String str : list) {
            String[] split = str.split(ChargePredictFields.ins().char3);
            BigDecimal factorVal = new BigDecimal(split[1]);
            sum = sum.add(factorVal);
        }
        BigDecimal avg = sum.divide(new BigDecimal(list.size()), BigDecimal.ROUND_HALF_UP);
        jsonObject.put("avg",avg);
        return jsonObject;
    }
    /**
     * @description:  计算电流map表的坐标点
     * @author:  GW00280745
     * @date: 2022/5/17 10:49
     * @param: line
     * @return:
     * @return: java.lang.String vin#obc#dc#(温度,SOC)
     **/
    public String axisBatter(JSONObject line,String soc,String temp, Map<String, Object> confMap,boolean appendFlag){
        Map<String, Integer> axisMap = batterMapRangeFormat(confMap);
        if (StringUtils.isBlank(temp)){
            temp = line.getString(ChargePredictFields.ins().stdFieldTemp);
        }
        if (StringUtils.isBlank(soc)){
            soc = line.getString(ChargePredictFields.ins().srcFieldBmsSoc);
        }
        String axis = batterMapAxis(line,temp,soc,axisMap,appendFlag);
        String dcConnect = line.getString(ChargePredictFields.ins().srcFieldBmsDcConnect);
        String obcConnect = line.getString(ChargePredictFields.ins().srcFieldBmsObcConnect);
        String vehicleType = line.getString(ChargePredictFields.ins().srcFieldVehicleType);
        vehicleType=StringUtils.isBlank(vehicleType)?ChargePredictFields.ins().blankStr:vehicleType;
        String batterType = line.getString(ChargePredictFields.ins().srcFieldBatterType);
        batterType = StringUtils.isBlank(batterType)?ChargePredictFields.ins().blankStr:batterType;
        //redis-key设计redis-key设计
        //				原则 业务名称：数据名：id
        //					 dws_charge_predict:batterAccMap_v2:ES13#磷酸铁锂电池#0#1#([10,15),[10,15))
        //						实际运用= 业务名称代号:数据名代号:id代号
        //						DCP:B2:1#1#0#1#([10,15),[10,15))
        //					 长度不超过44字节
        //						优化后的字节是32
        //					 不包含特殊字符
        //						有普通字符
        String key = ChargeInfo.single().getVehicleType(vehicleType).toString().concat(ChargePredictFields.ins().char3)
                .concat(ChargeInfo.single().getBatterType(batterType).toString()).concat(ChargePredictFields.ins().char3)
                .concat(obcConnect).concat(ChargePredictFields.ins().char3)
                .concat(dcConnect).concat(ChargePredictFields.ins().char3)
                .concat(axis)
                ;
        return key;
    }
    private String batterMapAxis(JSONObject dwsLine,String temp,String soc,Map<String, Integer> axisMap,boolean appendFlag){
        //电流map横坐标 温度
//        Integer startX = axisMap.getOrDefault(EndTempConstant.startX_batterMap,-25)
        Integer startX = -25;
//        Integer endX = axisMap.getOrDefault(EndTempConstant.endX_batterMap,55)
        Integer endX = 55;
//        Integer stepX  axisMap.getOrDefault(EndTempConstant.stepX_batterMap,1)
        Integer stepX = 5;
        String axisX = axis(temp,startX,endX,stepX);
        if (appendFlag){
            dwsLine.put(ChargePredictFields.ins().stdFieldBatterMapTempRange,axisX);
        }
        //电流map纵坐标 SOC
//        Integer startY = axisMap.getOrDefault(EndTempConstant.startY_batterMap,0)
        Integer startY = 0;
//        Integer endY = axisMap.getOrDefault(EndTempConstant.endY_batterMap,100)
        Integer endY = 100;
//        Integer stepY = axisMap.getOrDefault(EndTempConstant.stepY_batterMap,1)
        Integer stepY = 5;
        String axisY = axis(soc,startY,endY,stepY);
        if (appendFlag){dwsLine.put(ChargePredictFields.ins().stdFieldBatterMapSocRange,axisY);}
        return ChargePredictFields.ins().leftParentheses.concat(axisX).concat(ChargePredictFields.ins().comma).concat(axisY).concat(ChargePredictFields.ins().rightParentheses);
    }
    private Map<String,Integer> batterMapRangeFormat(Map<String,Object> confMap){
        HashMap<String, Integer> axisMap = new HashMap(8);
        //横坐标 --温度
        axisMap.put(ChargePredictFields.ins().startxBattermap, confMapVal(confMap, ChargePredictFields.ins().paramBatterMapTempStart,-20));
        axisMap.put(ChargePredictFields.ins().endxBattermap, confMapVal(confMap,ChargePredictFields.ins().paramBatterMapTempEnd,35));
//        axisMap.put(EndTempConstant.stepX_batterMap, confMapVal(confMap,BmsParamField.param_batterMap_tempStep,1))
        axisMap.put(ChargePredictFields.ins().stepxBattermap, 1);
        //纵坐标 --soc
        axisMap.put(ChargePredictFields.ins().startyBattermap, confMapVal(confMap,ChargePredictFields.ins().paramBatterMapSocStart,0));
        axisMap.put(ChargePredictFields.ins().endyBattermap, confMapVal(confMap,ChargePredictFields.ins().paramBatterMapSocEnd,100));
        axisMap.put(ChargePredictFields.ins().stepyBattermap, 1);
        return axisMap;
    }

    private Integer confMapVal(Map<String,Object> confMap,String confKey,Integer defaultVal){
        try {
            int i = Integer.parseInt(confMap.get(confKey).toString());
            return i;
        }catch (Exception e){
//            e.printStackTrace()
            return defaultVal;
        }
    }
    /**
     * @description: 获取温升map坐标信息
     * @author:  GW00280745
     * @date: 2022/5/11 17:24
     * @param: line
     * @return: java.lang.String vin#cool_heat_sts#(温度范围,电流范围)
     **/
    public String axisTempAcc(JSONObject line, String batter, String temp, Map<String, Object> confMap,boolean appendFlag){
        Map<String, Integer> axisMap = tempAccRangeFormat(confMap);
        Integer tempInt = line.getInteger(ChargePredictFields.ins().stdFieldTemp);
        if (StringUtils.isBlank(temp)){
            temp = tempInt.toString();
        }
        if (StringUtils.isBlank(batter)){
            batter = line.getString(ChargePredictFields.ins().srcFieldBmsBatterCurrRm);
        }
        batter=batter.replaceAll("-","");
        //电池包状态
        String heat = line.getString(ChargePredictFields.ins().srcFieldBmsHeatReq);
        String cool = line.getString(ChargePredictFields.ins().srcFieldBmsCoolReq);
        String heatManagerSts = tempHeatManagerSts(heat,cool,temp,line,appendFlag);
        //横坐标 --温度
        Integer startX = axisMap.get(ChargePredictFields.ins().startxtempacc);
        Integer endX = axisMap.get(ChargePredictFields.ins().endxtempacc);
        Integer stepX = axisMap.get(ChargePredictFields.ins().stepxtempacc);
        String axisX = axis(temp,startX,endX,stepX);
        if (appendFlag){
            line.put(ChargePredictFields.ins().stdFieldTempAccTempRange,axisX);
        }
        //纵坐标 --电流
        Integer startY = axisMap.get(ChargePredictFields.ins().startyTempacc);
        Integer endY = axisMap.get(ChargePredictFields.ins().endyTempacc);
        Integer stepY = axisMap.get(ChargePredictFields.ins().stepyTempacc);
        String axisY = axis(batter,startY,endY,stepY);
        if (appendFlag){
            line.put(ChargePredictFields.ins().stdFieldTempAccBatterRange,axisY);
        }
        //合成一个axis点
        String axis = ChargePredictFields.ins().leftParentheses.concat(axisX).concat(ChargePredictFields.ins().comma).concat(axisY).concat(ChargePredictFields.ins().rightParentheses);
        //axis_group: vin#cool_heat_sts#(x,y)
        String vehicleType = line.getString(ChargePredictFields.ins().srcFieldVehicleType);
        vehicleType= StringUtils.isBlank(vehicleType)?ChargePredictFields.ins().blankStr:vehicleType;
        String batterType = line.getString(ChargePredictFields.ins().srcFieldBatterType);
        batterType = StringUtils.isBlank(batterType)?ChargePredictFields.ins().blankStr:batterType;

        String key = ChargeInfo.single().getVehicleType(vehicleType).toString().concat(ChargePredictFields.ins().char3)
                .concat(ChargeInfo.single().getBatterType(batterType).toString()).concat(ChargePredictFields.ins().char3)
                .concat(heatManagerSts).concat(ChargePredictFields.ins().char3)
                .concat(axis);
        return key;
    }
    private Map<String,Integer> tempAccRangeFormat(Map<String,Object> confMap){
        HashMap<String, Integer> axisMap = new HashMap(8);
        //横坐标 --温度
        axisMap.put(ChargePredictFields.ins().startxtempacc, confMapVal(confMap,ChargePredictFields.ins().paramTempAccTempStart,-20));
        axisMap.put(ChargePredictFields.ins().endxtempacc, confMapVal(confMap,ChargePredictFields.ins().paramTempAccTempEnd,55));
        axisMap.put(ChargePredictFields.ins().stepxtempacc, confMapVal(confMap,ChargePredictFields.ins().paramTempAccTempStep,2));
        //纵坐标 --电流
        axisMap.put(ChargePredictFields.ins().startyTempacc, confMapVal(confMap,ChargePredictFields.ins().paramTempAccBatterStart,0));
        axisMap.put(ChargePredictFields.ins().endyTempacc, confMapVal(confMap,ChargePredictFields.ins().paramTempAccBatterEnd,200));
        axisMap.put(ChargePredictFields.ins().stepyTempacc, confMapVal(confMap,ChargePredictFields.ins().paramTempAccBatterStep,2));
        return axisMap;
    }
    private String blankStr = "";
    private String comma = ",";
    private String greatEq = ">=";
    private String less = "<";
    private String rightParentheses = ")";
    private String leftMidParentheses = "[";
    /**
     * @description: 求某个值所在范围 例如 (21,-25,30,5)  => [20,25)
     * @author:  GW00280745
     * @date: 2022/7/23 15:33
     * @param: value 当前值
     * @param: start 开头
     * @param: end   结尾
     * @param: step  步长
     * @return: java.lang.String  [20,25)
     **/
    public String axis(String value, int start, int end, int step) {
        if (StringUtils.isBlank(value)){
            return blankStr;
        }
        try {
            Double.parseDouble(value);
        }catch (NumberFormatException nfe){
            nfe.printStackTrace();
            return value;
        }
        double v = Double.parseDouble(value);
        if (v>=end){
            return  greatEq.concat(String.valueOf(end));
        }else if (v < start){
            return less.concat(String.valueOf(start));
        }
        for (int i = start; i < end; i=i+step) {
            if (v >= i && v < i+step){
                return leftMidParentheses.concat(String.valueOf(i))
                        .concat(comma)
                        .concat(String.valueOf(i+step))
                        .concat(rightParentheses)
                        ;
            }
        }
        return blankStr;
    }
    /**
     * @description: 获取电池包热管理状态
     * @author:  GW00280745
     * @date: 2022/5/11 17:43
     * @param: heat
     * @param: cool
     * @param: temp
     * @return: java.lang.String
     **/
    public String tempHeatManagerSts(String heat, String cool, String temp,JSONObject line,boolean appendFlag) {
        String heatSignal=null;
        String coolSignal=null;
        if (org.apache.commons.lang3.StringUtils.equals(heat,DwsStrConstant.ins().num0X1)){
            heatSignal=heat;
        }else if (org.apache.commons.lang3.StringUtils.equals(cool,DwsStrConstant.ins().num0X2) ||
                org.apache.commons.lang3.StringUtils.equals(cool,DwsStrConstant.ins().num0X3) ||
                org.apache.commons.lang3.StringUtils.equals(cool,DwsStrConstant.ins().num0X4)){
            coolSignal=cool;
        }
        //1 -- 无加热无制冷
        if (heatSignal==null && coolSignal==null){
            if (appendFlag){
                //0代表是加热 1代表是制冷 2无加热无制冷 3代表err
                line.put(ChargePredictFields.ins().stdFieldHeatSts,"2");
            }
//            return "non_heat_cool"
            return "2";
        }
        //2 -- 加热
        if (heatSignal!=null && coolSignal==null){
            if (appendFlag){
                //0代表是加热 1代表是制冷 2无加热无制冷 3代表err
                line.put(ChargePredictFields.ins().stdFieldHeatSts,"0");
            }
//            return "heat"
            return "0";
        }
        //3 -- 制冷
        if (heatSignal==null && coolSignal!=null){
            if (appendFlag){
                //0代表是加热 1代表是制冷 2无加热无制冷 3代表err
                line.put(ChargePredictFields.ins().stdFieldHeatSts,"1");
            }
//            return "cool"
            return "1";
        }
        double v = Double.parseDouble(temp);
        if (v>=DwsStrConstant.ins().num20){
            //-- 加热
            if (appendFlag){
                //0代表是加热 1代表是制冷 2无加热无制冷 3代表err
                line.put(ChargePredictFields.ins().stdFieldHeatSts,"0");
            }
//            return "heat"
            return "2";
        }else {
            //-- 制冷
            if (appendFlag){
                //0代表是加热 1代表是制冷 2无加热无制冷 3代表err
                line.put(ChargePredictFields.ins().stdFieldHeatSts,"1");
            }
//            return "cool"
            return "0";
        }
    }
}
